#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>

#include "libmod.h"
#include "log.h"
#include "confparser.h"
#include "http.h"

int mod_init(char *);

static ssize_t	writen(int fd, const void *vptr, size_t n);
static void split_url_para(char *uri, char **url, char **para);  
static FILE *check_file(char *url, char *file_path_buf);                                     
const char *getmimetype(const char *name);
static void _send_file(FILE *handler, HTTP_REQUEST *req_info, ssize_t content_length);
static int create_response_header(char *buf, const char *status, char *host, 
                                   char *url, ssize_t file_size, const char *file_mime);

const char *default_page[] = {SITE_DEFAULT_PAGE, NULL};
char SITE_ROOT_DIR[SITE_ROOT_DIR_LENGTH + 1]; 

const char http_404[] = "<html><head><title>404 Not Found</title></head><body>\
<h1>404 Not Found</h1><h2>The document requested was not found.</h2></body></html>";
const char http_500[] = "<html><head><title>500 Server Error</title></head><body>\
<h1>500 Server Error</h1><h2>Server Internal Error.</h2></body></html>";
const char http_414[] = "<html><head><title>414 Bad Request</title></head><body>\
<h1>414 Bad Request</h1><h2>Request-URI Too Long.</h2></body></html>";


static struct conf_str_config conf_str_array[] = {
	{"site_root_dir", SITE_ROOT_DIR}, 
	{0, 0}
};


/* the mime table */
struct mime_struct
{
    const char *ext;
    const char *type;
};

struct mime_struct mime_table[] = {
    { ".html", "text/html" },
    { ".htm", "text/html" },
    { ".txt", "text/plain" },
    { ".rtx", "text/richtext" },
    { ".etx", "text/x-setext" },
    { ".tsv", "text/tab-separated-values" },
    { ".css", "text/css" },
    { ".xml", "text/xml" },
    { ".dtd", "text/xml" },
    { ".gif", "image/gif" },
    { ".jpg", "image/jpeg" },
    { ".jpeg", "image/jpeg" },
    { ".jpe", "image/jpeg" },
    { ".jfif", "image/jpeg" },
    { ".tif", "image/tiff" },
    { ".tiff", "image/tiff" },
    { ".pbm", "image/x-portable-bitmap" },
    { ".pgm", "image/x-portable-graymap" },
    { ".ppm", "image/x-portable-pixmap" },
    { ".pnm", "image/x-portable-anymap" },
    { ".xbm", "image/x-xbitmap" },
    { ".xpm", "image/x-xpixmap" },
    { ".xwd", "image/x-xwindowdump" },
    { ".ief", "image/ief" },
    { ".png", "image/png" },
    { ".au", "audio/basic" },
    { ".snd", "audio/basic" },
    { ".aif", "audio/x-aiff" },
    { ".aiff", "audio/x-aiff" },
    { ".aifc", "audio/x-aiff" },
    { ".ra", "audio/x-pn-realaudio" },
    { ".ram", "audio/x-pn-realaudio" },
    { ".rm", "audio/x-pn-realaudio" },
    { ".rpm", "audio/x-pn-realaudio-plugin" },
    { ".wav", "audio/wav" },
    { ".mid", "audio/midi" },
    { ".midi", "audio/midi" },
    { ".kar", "audio/midi" },
    { ".mpga", "audio/mpeg" },
    { ".mp2", "audio/mpeg" },
    { ".mp3", "audio/mpeg" },
    { ".mpeg", "video/mpeg" },
    { ".mpg", "video/mpeg" },
    { ".mpe", "video/mpeg" },
    { ".qt", "video/quicktime" },
    { ".mov", "video/quicktime" },
    { ".avi", "video/x-msvideo" },
    { ".movie", "video/x-sgi-movie" },
    { ".mv", "video/x-sgi-movie" },
    { ".vx", "video/x-rad-screenplay" },
    { ".a", "application/octet-stream" },
    { ".bin", "application/octet-stream" },
    { ".exe", "application/octet-stream" },
    { ".dump", "application/octet-stream" },
    { ".o", "application/octet-stream" },
    { ".class", "application/java" },
    { ".js", "application/x-javascript" },
    { ".ai", "application/postscript" },
    { ".eps", "application/postscript" },
    { ".ps", "application/postscript" },
    { ".dir", "application/x-director" },
    { ".dcr", "application/x-director" },
    { ".dxr", "application/x-director" },
    { ".fgd", "application/x-director" },
    { ".aam", "application/x-authorware-map" },
    { ".aas", "application/x-authorware-seg" },
    { ".aab", "application/x-authorware-bin" },
    { ".fh4", "image/x-freehand" },
    { ".fh7", "image/x-freehand" },
    { ".fh5", "image/x-freehand" },
    { ".fhc", "image/x-freehand" },
    { ".fh", "image/x-freehand" },
    { ".spl", "application/futuresplash" },
    { ".swf", "application/x-shockwave-flash" },
    { ".dvi", "application/x-dvi" },
    { ".gtar", "application/x-gtar" },
    { ".hdf", "application/x-hdf" },
    { ".hqx", "application/mac-binhex40" },
    { ".iv", "application/x-inventor" },
    { ".latex", "application/x-latex" },
    { ".man", "application/x-troff-man" },
    { ".me", "application/x-troff-me" },
    { ".mif", "application/x-mif" },
    { ".ms", "application/x-troff-ms" },
    { ".oda", "application/oda" },
    { ".pdf", "application/pdf" },
    { ".rtf", "application/rtf" },
    { ".bcpio", "application/x-bcpio" },
    { ".cpio", "application/x-cpio" },
    { ".sv4cpio", "application/x-sv4cpio" },
    { ".sv4crc", "application/x-sv4crc" },
    { ".sh", "application/x-shar" },
    { ".shar", "application/x-shar" },
    { ".sit", "application/x-stuffit" },
    { ".tar", "application/x-tar" },
    { ".tex", "application/x-tex" },
    { ".texi", "application/x-texinfo" },
    { ".texinfo", "application/x-texinfo" },
    { ".tr", "application/x-troff" },
    { ".roff", "application/x-troff" },
    { ".man", "application/x-troff-man" },
    { ".me", "application/x-troff-me" },
    { ".ms", "application/x-troff-ms" },
    { ".zip", "application/x-zip-compressed" },
    { ".tsp", "application/dsptype" },
    { ".wsrc", "application/x-wais-source" },
    { ".ustar", "application/x-ustar" },
    { ".cdf", "application/x-netcdf" },
    { ".nc", "application/x-netcdf" },
    { ".doc", "application/msword" },
    { ".ppt", "application/powerpoint" },
    { ".wrl", "model/vrml" },
    { ".vrml", "model/vrml" },
    { ".mime", "message/rfc822" },
    { ".pac", "application/x-ns-proxy-autoconfig" },
    { ".wml", "text/vnd.wap.wml" },
    { ".wmlc", "application/vnd.wap.wmlc" },
    { ".wmls", "text/vnd.wap.wmlscript" },
    { ".wmlsc", "application/vnd.wap.wmlscriptc" },
    { ".wbmp", "image/vnd.wap.wbmp" },
    { ".tgz", "application/x-gzip" },
    { ".tar.gz", "application/x-gzip" },
    { ".bz2", "application/x-bzip2" },
    { ".rar", "application/x-zip-compressed" },
    { ".iso", "application/x-zip-compressed" }
};


/* get the mime type via extand name */
const char *
getmimetype(const char *name) 
{
    unsigned int namelen, extlen, i;
    
    if (name == NULL)
    {
        return mime_table[0].type;
    }
    
    namelen = strlen(name);
    
    for (i=0; i < sizeof(mime_table)/sizeof(*mime_table); i++) 
    {
        extlen = strlen(mime_table[i].ext);
        if (extlen != namelen)
        {
            continue;
        }

        if (strcmp(name, mime_table[i].ext) == 0)
        {
            return mime_table[i].type;
        }
    }
    return mime_table[0].type;
}


/* write n bytes to a fd */
static ssize_t	
writen(int fd, const void *vptr, size_t n)
{
	size_t		nleft;
	ssize_t		nwritten;
	const char	*ptr;

	ptr = vptr;
	nleft = n;
	while (nleft > 0) {
		if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
			if (errno == EINTR)
				nwritten = 0;		/* and call write() again */
			else
				return(-1);			/* error */
		}

		nleft -= nwritten;
		ptr   += nwritten;
	}
	return(n);
}


/* split url and parameters 
 * in:  uri : /aaa.htm?b=1  
 * out: url : /aaa.htm  para : b=1
 */
static void
split_url_para(char *uri, char **url, char **para)
{
    if (uri == NULL)
    {
        return;
    }
    
    /* parse the uri. split from '?' */
    *url = uri;
    while ( *uri != '\0')
    {
        if ( *uri == '?')
        {
            *uri = '\0';
            if (*(uri + 1) != '\0')
            {
                *para = uri + 1;
            }
            return;
        }
        uri++;
    }
}


/* 
 * check a file by given url.
 * if the file exists and can be opened, a file pointer FILE * is returned,
 * and the file_path_buf is set to the actually opened file path.
 * otherwise, a NULL pointer is returned and file_path_buf is ignored.
 */
static FILE *
check_file(char *url, char *file_path_buf)
{
    FILE *handler;
    char file_path[REQUEST_URL_MAX_LENGTH + sizeof(SITE_ROOT_DIR)];
    char file_path_temp[REQUEST_URL_MAX_LENGTH + sizeof(SITE_ROOT_DIR)];
    const char **default_page_t;
    
    if (url == NULL || file_path_buf == NULL)
    {
        return NULL;
    }
    
    /* join the site_root and url together */
    strncpy(file_path, SITE_ROOT_DIR, sizeof(file_path));
    strncat(file_path, url, sizeof(file_path));
    
    #ifdef DEBUG
    printf("file_path:%s\n",file_path);
    #endif
    
    /* check this is whether a directory path or a file path */
    if (file_path[strlen(file_path) - 1] == '/')    /* this is a directory path */
    {
        #ifdef DEBUG
        printf("dir path\n");
        #endif
        /* open the default page if exist.otherwise return 404 page not found */
        default_page_t = default_page;
        while (*default_page_t != NULL)
        {
            strncpy(file_path_temp, file_path, sizeof(file_path_temp));
            strncat(file_path_temp, *default_page_t, sizeof(file_path_temp));
            
            #ifdef DEBUG
            printf("final path:%s\n",file_path_temp);
            #endif
           
            default_page_t++;
            
            handler = fopen(file_path_temp, "rb");
            if (handler != NULL)
            {
                strcpy(file_path_buf, file_path_temp);
                return handler;
            }
        }
        
        if (handler == NULL)
        {
            return NULL;
        }
    }
    else    /* this is a file path */
    {   
        #ifdef DEBUG
        printf("file path\n");
        #endif
        
        strcpy(file_path_buf, file_path);
        handler = fopen(file_path, "rb");
        return handler;
    }
    
    return NULL;
}


/* send the given file via socket */
static void
_send_file(FILE *handler, HTTP_REQUEST *req_info, ssize_t content_length)
{
    int64_t flags;

    /* Set socket to blocking */ 
    if ((flags = fcntl(req_info->request_fd, F_GETFL, 0)) < 0) 
    { 
        WLOG_ERR("[HTTP] error when get the socket flag"); 
        return;
    } 

    if (fcntl(req_info->request_fd, F_SETFL, flags & (~O_NONBLOCK)) < 0) 
    { 
        WLOG_ERR("[HTTP] error when set socket to blocking mod"); 
        return;
    } 
    
    /* sending file with read & write system call */
    #if HOW_TO_RESPONSE_FILE == COMMON
    int64_t read_objects = 0;
    int64_t write_objects = 0;
    unsigned char buf[RESPONSE_FILE_BUF_LENGTH];
    
    CSF_UNUSED_ARG(content_length);
    while (feof(handler) == 0)
    {
        read_objects = fread(buf, 1, RESPONSE_FILE_BUF_LENGTH, handler);
        if (read_objects < 0)
        {
            WLOG_ERR("[HTTP] error when response a file"); 
            break;
        }
        write_objects = write(req_info->request_fd, buf, read_objects);
        if (write_objects < 0)
        {
            WLOG_ERR("[HTTP] error when response a file"); 
            //perror("");
            break;
        }

        #ifdef DEBUG
        printf("read = %ld\n", read_objects);
        printf("write = %ld\n", write_objects);
        #endif
    }
    #endif
    
    /* sending file with sendfile system call */
    #if HOW_TO_RESPONSE_FILE == FREEBSD
    CSF_UNUSED_ARG(content_length);
    flags = sendfile(fileno(handler), req_info->request_fd, 0, 0, NULL, NULL, 0);
    #endif
    
    #if HOW_TO_RESPONSE_FILE == LINUX
    flags = sendfile(req_info->request_fd, fileno(handler), (off_t *)0 , (size_t)content_length);
    #endif
    
    if (flags == -1)
    {
        WLOG_ERR("[http]response file failed. %s", strerror(errno));
    }
    
    /* Set socket back to non-blocking */ 
    if ((flags = fcntl(req_info->request_fd, F_GETFL, 0)) < 0) 
    { 
        WLOG_ERR("[HTTP] error when get the socket flag"); 
        return;
    } 

    if (fcntl(req_info->request_fd, F_SETFL, flags | O_NONBLOCK) < 0)
    { 
        WLOG_ERR("[HTTP] error when set socket to non-blocking mod"); 
        return;
    }
    
}


/* create the response header, result in char *buf */
static int 
create_response_header(char *buf, const char *status, char *host, char *url, 
                       ssize_t file_size, const char *file_mime)
{
    struct tm *tm_ptr;
    time_t the_time;
    char *asc_time;
    const char *server;
    
    if (buf == NULL || status == NULL || host == NULL || url == NULL
        || file_mime == NULL)
    {
        return -1;
    }
    
    /* get host time */
    time(&the_time);
    tm_ptr = gmtime(&the_time);
    asc_time = asctime(tm_ptr);
    asc_time[strlen(asc_time) - 1] = '\0';  /* delete the last '\n' */
    
    server = "CSF Http Server 1.0";         /* server information */
    
    snprintf(buf, RESPONSE_BUF_MAX_LENGTH, 
                "%s\r\nDate: %s\r\nServer: %s\r\nLocation: %s%s\r\n"
                "Content-Length: %ld\r\nContent-Type: %s\r\n"
                "\r\n",
                status, asc_time, server, host, url, file_size, file_mime);
    
    
    /*
    strcat(buf, status);
    strcat(buf, "\r\nDate: ");
    strcat(buf, asc_time);
    strcat(buf, "\r\nServer: ");
    strcat(buf, "\r\nLocation: ");
    strcat(buf, host);
    strcat(buf, url);
    strcat(buf, "\r\nContent-Length: ");
    strcat(buf, file_size);
    strcat(buf, "\r\nContent-Type: ");
    strcat(buf, file_mime);
    */
    
    return 1;
}


static ssize_t 
socket_handler(WTI *wtip, CONN_INFO *cip, void *data, void **res)
{
    FILE *handler = NULL;
    HTTP_REQUEST *req_info;   
    char *url = NULL;
    char is_file_opened = 0;
    char *parameter = NULL;
    char *extand_name = NULL;
    char response_buf[RESPONSE_BUF_MAX_LENGTH];
    char file_path_buf[REQUEST_URL_MAX_LENGTH];
    const char status[] = "HTTP/1.0 200 OK";
    const char *content_type = NULL;
    const char *response_entity = NULL;
    ssize_t content_length;
    struct stat st;
    
    CSF_UNUSED_ARG(res);
    CSF_UNUSED_ARG(cip);
    CSF_UNUSED_ARG(wtip);
    
    req_info = (HTTP_REQUEST *)data;
    memset(response_buf, '\0', RESPONSE_BUF_MAX_LENGTH);
    memset(file_path_buf, '\0', REQUEST_URL_MAX_LENGTH);
   
	/* writev */
	/*
	int i;
	const char *data1 = "[1]this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.vvvvvvv";
	const char *data2 = "[2]this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.";
	const char *data3 = "[3]this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.";
	const char *data4 = "[4]this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.vvvvthis is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.";
	const char *data5 = "[5]this is my data.vthis is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.";
	const char *data6 = "[6]this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.v";
	const char *data7 = "[7]this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.v";
	const char *data8 = "[8]this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.vv";
	const char *data9 = "[9]this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.v";
	const char *data10 = "[10]this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.this is my data.v";

	char *datatt[10];
	datatt[0] = (char *)malloc(100);
	strcpy(datatt[0], data1);
	datatt[1] = (char *)malloc(100);
	strcpy(datatt[1], data2);
	datatt[2] = (char *)malloc(100);
	strcpy(datatt[2], data3);
	datatt[3] = (char *)malloc(100);
	strcpy(datatt[3], data4);
	datatt[4] = (char *)malloc(100);
	strcpy(datatt[4], data5);
	datatt[5] = (char *)malloc(100);
	strcpy(datatt[5], data6);
	datatt[6] = (char *)malloc(100);
	strcpy(datatt[6], data7);
	datatt[7] = (char *)malloc(100);
	strcpy(datatt[7], data8);
	datatt[8] = (char *)malloc(100);
	strcpy(datatt[8], data9);
	datatt[9] = (char *)malloc(100);
	strcpy(datatt[9], data10);

	struct iovec new_vector[IOV_MAX];

	for(i=0; i<1000;i++){
		new_vector[i].iov_base = datatt[(i+1) % 10];
		new_vector[i].iov_len = strlen(datatt[(i+1) % 10]);
	}

	for (i=0;i<10;i++){
	writev_back(cip, new_vector, 1000);
		}
*/

	usleep(100000000);

    /* split url and parameters index[1] is 'uri' */
    split_url_para(req_info->header_field_ptr[URI].field_value, &url, &parameter);

    if (url == NULL)
    {
        WLOG_ERR("[HTTP] parsing url failed. bad request header.");
        return (PIPELINE_FAILED);
    }

    /* http 414  request uri too long */
    if (strlen(url) > REQUEST_URL_MAX_LENGTH)
    {
        content_type = getmimetype("text/html");
        content_length = sizeof(http_414) - 1;
        response_entity = http_414;
    }
    
    #ifdef DEBUG
    printf("url:%s\n",url);
    printf("parameter:%s\n",parameter);
    #endif
       
    /* check the requset resource and set the actual file path*/
    handler = check_file(url, file_path_buf);
    if (handler == NULL)        /* http 404 */
    {
        content_type = getmimetype("text/html");
        content_length = sizeof(http_404) - 1;
        response_entity = http_404;
    }
    else                        /* file is available */
    {
        is_file_opened = 1;
        
        if (fstat(fileno(handler), &st) < 0)    /* can not get file size http 500 */
        {
            content_type = getmimetype("text/html");
            content_length = sizeof(http_500) - 1;
            response_entity = http_500;
        }
        else    /* every thing goes well, we send the file via socket */
        {
            /* get the extend name of the file via actual path */
            extand_name = file_path_buf;
            while (*extand_name != '\0')
            {
                if (*extand_name == '.')break;
                extand_name++;
            }
            
            /* get the mime type via extand name */
            content_type = getmimetype(extand_name);
            content_length = st.st_size;
            response_entity = NULL;
        }
    }
    
    /* send http head */
    create_response_header(response_buf, status, 
                               req_info->header_field_ptr[HOST].field_value, url, 
                               content_length, content_type);

    
    /* send header */                          
    writen(req_info->request_fd, response_buf, strlen(response_buf));
    
    /* send entity */
    if (response_entity == NULL)
    {
        _send_file(handler, req_info, content_length);
    }
    else
    {
        writen(req_info->request_fd, response_entity, content_length);
    }
    
    if (is_file_opened)
    {
        fclose(handler);
    }
    
    req_info->state = HTTP_PIPE_LINE_DONE;
    
    #ifdef DEBUG
    printf("\n***final path:***\n%s\n", file_path_buf);
    printf("\n***final response:***\n%s\n", response_buf);
    #endif
    
    return (PIPELINE_CONTINUE);
}


static ssize_t
http_init(void *arg, void **res)
{
	char mod_name[] = "http_io.so";
	int r;

	CSF_UNUSED_ARG(res);
	
	if(((WTI *)arg)->thr_seq_num == 0)
	{ 
		r = load_conf(NULL, mod_name, NULL, conf_str_array);
	
		if (r != 0)
		{
			WLOG_ERR("http_init load_conf() failed!");	
		}
	}
		
    return MOD_INIT_OK;
}

static void
http_deinit(void *arg, void *res)
{
	CSF_UNUSED_ARG(arg);
	CSF_UNUSED_ARG(res);
	
	if(((WTI *)arg)->thr_seq_num == 0)
	{
		printf("http deinit.\n");
	}
		
    return;
}


int 
mod_init(char *mod_name)
{
	CSF_UNUSED_ARG(mod_name);
	
	set_request_init(http_init);
	set_request_deinit(http_deinit);
	set_request_handler(socket_handler);

	return (0);
}





